import React, { PureComponent } from 'react';
import { BaseForm } from '@/components/FormTools';
import { Select, message, Button, Row, Col, Form, Radio, Input, Checkbox } from 'antd';
import styles from './index.less';
import configData from './config-data';
import { pushedNoticeNumber, getConfigAppId } from '@/services/push';
import { to } from '@/utils/smallTool';
import { validate } from '@babel/types';
import auth from '@/utils/auth';
import CryptoJS from 'crypto-js';

const createInput = (list = [], disabled = false) => {
    return <Input disabled={disabled}></Input>
}
const createCombinationInput = (list = [], disabled = false) => {
    const [beforeNode, afterNode] = list;
    return <Input addonBefore={beforeNode.value} addonAfter={afterNode.value} disabled={disabled} />
}
const createTextarea = (list = [], disabled = false) => {
    return <Input.TextArea disabled={disabled}></Input.TextArea>
}
const createSelect = (list = [], disabled = false) => {
    return <Select placeholder={'请选择'} disabled={disabled}>
        {
            list.map((item) => (
                <Select.Option lable={item.name} key={item.value} value={item.value}>
                    {item.name}
                </Select.Option>
            ))
        }
    </Select>
}
const createCheckbox = (list = []) => {
    return <Checkbox.Group>
        {
            list.map((item) => {
                return <Checkbox value={item.value} key={item.value}>{item.name}</Checkbox>
            })
        }
    </Checkbox.Group>
}
const createRadio = (list = []) => {
    return <Radio.Group>
        {
            list.map((item) => {
                return <Radio value={item.value} key={item.value}>{item.name}</Radio>
            })
        }
    </Radio.Group>
}
const getContext = (selector) => {
    const config = {
        input: createInput,
        select: createSelect,
        checkbox: createCheckbox,
        radio: createRadio,
        textarea: createTextarea,
        combinationinput: createCombinationInput
    }
    return config[selector];
}
class HandleCreate {
    context = null
    constructor(selector) {
        this.context = getContext(selector);
    }
    createNode(buildParams) {
        let list = buildParams.optionList && buildParams.optionList.list || [];
        list = list.map((item) => {
            return {
                name: item[buildParams.nameFiled || 'name'],
                value: item[buildParams.valueFiled || 'value']
            }
        })
        return this.context(list, buildParams.disabled);
    }
}
// 缓存实例化
class CreateFactory {
    examples = {};
    getExample(selector) {
        let oExample = this.examples[selector];
        if (oExample === undefined) {
            oExample = this.examples[selector] = new HandleCreate(selector)
        }
        return oExample;
    }
}
const formItemLayout = {
    labelCol: {
        xs: { span: 6 },
        sm: { span: 6 },
    },
    wrapperCol: {
        xs: { span: 16 },
        sm: { span: 16 },
    },
    labelAlign: 'left',
};
const { Option } = Select;
class Validate {
    static invalid = false;
    static isEmpty(value, rule) {
        return auth.isDef(value) && /\S/.exec(value) ? true : false;
    }
    static checkPattern(value, rule) {
        return auth.isDef(value) && /\S/.exec(value) ? true : false;
    }
    static checkDependent(value, rule) {
        return auth.isDef(value) && /\S/.exec(value) ? true : false;
    }
    static handleValidate(value, rules) {
        if (typeof rules === 'undefined') return [true];
        const checkConfig = {
            'required': this.isEmpty,
            'pattern': this.checkPattern,
            'dependent': this.checkDependent
        }
        let validateRes = rules.map((rule) => {
            return checkConfig[rule.type](value, rule);
        })
        return validateRes;
    }
    static showMessage(messageText) {
        message.error(messageText);
    }
    static excute(validateFields) {
        this.invalidIndex = -1;
        let errorItem;
        let fields = {};
        validateFields.forEach((item) => {
            const { value, name, rules } = item;
            // 只校验一次错误
            if (typeof errorItem === 'undefined') {
                const resArr = this.handleValidate(value, rules);
                this.invalidIndex = resArr.indexOf(false);
                if (~this.invalidIndex) {
                    errorItem = item;
                    errorItem.ruleErrorIndex = this.invalidIndex;
                    this.showMessage(rules[this.invalidIndex].message);
                }
            }
            fields[`${name}`] = value
        })
        return [errorItem, fields];
    }
}
@Form.create({})
class Push extends PureComponent {
    constructor(props) {
        super(props)
        this.state = {
            pushTarget: '',
            appIdConfig: [],
            receiverLoading: false
        }
        this.getConfigAppId();
    }
    setReceiverNoticeNumber(from, receiverData) {
        if (auth.isUndef(receiverData)) return;
        const { setFieldsValue } = from;
        const nameConfig = {
            'appCount': 'noticeNumver',
            'inBoxMsgCount': 'inBoxMsgCount'
        };
        const tempValidateRes = {};
        for (let [key, value] of Object.entries(receiverData)) {
            tempValidateRes[nameConfig[key]] = Object.values(value)[0];
        }
        setFieldsValue(tempValidateRes)
    }
    async getReceiverNoticeNumber(data) {
        this.setState({
            receiverLoading: true
        })
        const responseData = await pushedNoticeNumber(data);
        this.setState({
            receiverLoading: false
        })
        if (responseData && responseData.code === '000000') {
            return responseData.data;
        }
        return;
    }
    async getConfigAppId() {
        const responseData = await getConfigAppId();
        if (responseData && responseData.code === '000000' && responseData.data) {
            const arr = responseData.data.split(',');
            this.setState({ appIdConfig: [{ name: arr[1], value: arr[0] }] });
        }
        return;
    }
    setPushTargetValue(val) {
        this.setState({
            pushTarget: val
        })
    }
    changePushTarget(e) {
        this.setPushTargetValue(e)
    }
    validateData(from, validateConfg) {
        const validateFields = this.getFieldsByForm(validateConfg, from);
        return Validate.excute(validateFields)
    }
    getFieldsByForm(validateFields, form) {
        const { getFieldValue } = form;
        return validateFields.map((field) => {
            field.value = getFieldValue(field.name);;
            return field;
        })
    }
    async handleCheckReceiverNoticeNumber() {
        const validateConfg = [
            {
                name: 'tagsName'
            },
            {
                name: 'documentId'
            },
            {
                name: 'serviceType'
            },
            {
                name: 'cityCode'
            },
            {
                name: 'cityName'
            },
            {
                name: 'appid',
                rules: [
                    {
                        type: 'required',
                        message: '请选择应用名称'
                    }
                ]
            },
            {
                name: 'phoneType',
                rules: [
                    {
                        type: 'required',
                        message: '请选择手机类型',
                    }
                ]
            },
            {
                name: 'noticePassword',
                rules: [
                    {
                        type: 'required',
                        message: '请输入密码',
                    },
                    {
                        type: 'pattern',
                        value: [/[0-9]*/]
                    },
                    {
                        type: 'dependent',
                        value: ['phoneType']
                    }
                ]
            }
        ];
        let [validateError, validateRes] = this.validateData(this.props.form, validateConfg);
        if (validateError) return false;
        validateRes.noticePassword = CryptoJS.MD5(validateRes.noticePassword).toString();
        const [error, res] = await to(this.getReceiverNoticeNumber(validateRes));
        if (res) {
            this.setReceiverNoticeNumber(this.props.form, res.data);
        }
    }
    render() {
        const { pushTarget, receiverLoading, appIdConfig } = this.state;
        const { activeRecord, form } = this.props;
        const { getFieldDecorator } = form;
        const addonAfter = (<Button type="link" loading={receiverLoading} onClick={this.handleCheckReceiverNoticeNumber.bind(this)}>查看</Button>);
        const inputConfigData = configData.pushDrawerConfig(activeRecord, pushTarget, addonAfter, appIdConfig);
        const createFactory = new CreateFactory();
        return <Form className={styles.drawerContent}>
            <Form.Item label='推送类型' {...formItemLayout}>
                {
                    getFieldDecorator('pushType', {
                        initialValue: String(activeRecord.pushNoticeStatus) === '1' ? '1' : '0'
                    })(
                        <Select onChange={(e) => this.changePushTarget.bind(this)(e)}>
                            <Option value="0">多人推送</Option>
                            <Option value="1">单人推送</Option>
                        </Select>
                    )
                }
            </Form.Item>
            {
                inputConfigData.map((item) => {
                    return <Form.Item label={item.label} {...formItemLayout} key={item.name} hidden={item.isHide}>
                        {getFieldDecorator(`${item.name}`, {
                            initialValue: typeof item.initialValue === 'number' ? String(item.initialValue) : item.initialValue,
                            rules: [{ required: item.required, message: `${item.label}不能为空` }],
                        })(
                            createFactory.getExample(item.type).createNode(item)
                        )}
                    </Form.Item>
                })
            }
        </Form >
    }
}
export default Push;